package com.smallkingson.ylib.core.utils;

import com.smallkingson.ylib.core.Yr;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * Created by Administrator on 2016/12/19.
 */
public class PropertyDescriptor {

    String writePrefix = "set";
    String readPrefix = "get";

    public void setMethodMaker(MethodMaker methodMaker) {
        this.methodMaker = methodMaker;
    }

    public void setReadPrefix(String readPrefix) {
        this.readPrefix = readPrefix;
    }

    public void setWritePrefix(String writePrefix) {
        this.writePrefix = writePrefix;
    }

    public PropertyDescriptor(String readPrefix, String writePrefix) {
        this.readPrefix = readPrefix;
        this.writePrefix = writePrefix;
    }

    public PropertyDescriptor(MethodMaker methodMaker) {
        this.methodMaker = methodMaker;
    }

    public PropertyDescriptor() {
    }

    MethodMaker methodMaker = new MethodMaker() {
        //        Map<String, Method> cache = new HashMap<>();
        TwoKeyCache<Class, String, Method> writeCache = new TwoKeyCache<>();
        TwoKeyCache<Class, String, Method> readCache = new TwoKeyCache<>();

        @Override
        public Method getWriteMethod(Class clazz, String property, Object value) throws NoSuchMethodException {
            Method method = writeCache.get(clazz, property);
            if (method == null) {
                String name = writePrefix + property.substring(0, 1).toUpperCase()
                        + property.substring(1);
                method = clazz.getMethod(name, value.getClass());
                writeCache.put(clazz,property,method);
                Yr.d();
            }
            return writeCache.get(clazz, property);
        }

        String getSign(Class clazz, String methodName, Object... params) {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(clazz.hashCode())
                    .append("_")
                    .append(clazz.getName())
                    .append("_")
                    .append(methodName)
                    .append("_");
            for (Object param : params) {
                stringBuilder.append(param.getClass().getName())
                        .append("_");
            }
            return stringBuilder.toString();
        }
    };

    public void setProperty(Object object, String property, Object value) {
        try {
            Method writeMethod = methodMaker.getWriteMethod(object.getClass(), property, value);
            writeMethod.invoke(object, value);
        } catch (Exception e) {
            Yr.logError(property + "=" + value, e);
        }
    }

    interface MethodMaker {
        Method getWriteMethod(Class clazz, String property, Object value) throws NoSuchMethodException;
    }
}
